package org.example.netty.pipeline;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.concurrent.CountDownLatch;

/**
 * create by 尼恩 @ 疯狂创客圈
 **/
public class PipelineHotOperateTester {

    public static final int wirteInTime = 3;
    private static CountDownLatch countDownLatch;

    private static boolean isPowerOfTwo(int val) {
        return (val & -val) == val;
    }

    @BeforeEach
    public void initEach() {
        countDownLatch = new CountDownLatch(wirteInTime);
    }

    @DisplayName("测试处理器的热拔插")
    @Test
    public void testPipelineHotOperating() {
        ChannelInitializer<EmbeddedChannel> i = new ChannelInitializer<EmbeddedChannel>() {
            protected void initChannel(EmbeddedChannel ch) {
                ch.pipeline().addLast(new SimpleInHandlerA());
                ch.pipeline().addLast(new SimpleInHandlerB());
                ch.pipeline().addLast(new SimpleInHandlerC());

            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(i);
        ByteBuf buf = Unpooled.buffer();
        buf.writeInt(1);
        //第一次向通道写入站报文
        channel.writeInbound(buf);
        //第二次向通道写入站报文
        channel.writeInbound(buf);
        //第三次向通道写入站报文
        channel.writeInbound(buf);
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void isPowerOfTwoTest() {
        for (int i = 0; i < 1000_0000; i++) {
            if (isPowerOfTwo(i)) {
                System.out.println(i);
            }
        }
    }

    static class SimpleInHandlerA extends ChannelInboundHandlerAdapter {

        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println("入站处理器 A: 被回调 ");
            super.channelRead(ctx, msg);
            //从流水线删除当前Handler
            ctx.pipeline().remove(this);
        }
    }

    static class SimpleInHandlerB extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println("入站处理器 B: 被回调 ");
            super.channelRead(ctx, msg);
        }
    }

    static class SimpleInHandlerC extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println("入站处理器 C: 被回调 ");
            super.channelRead(ctx, msg);
            countDownLatch.countDown();
        }
    }

}
